home *** CD-ROM | disk | FTP | other *** search
/ Network Supervisor's Toolkit / Network Supervisor's Toolkit.iso / tools / nwtp06 / nwipx.pas < prev    next >
Pascal/Delphi Source File  |  1996-07-10  |  20KB  |  607 lines

  1. {$B-,V-,X+}
  2. UNIT nwIPX;
  3.  
  4. {$DEFINE ProtMode}
  5. {$IFDEF MSDOS} {$UNDEF ProtMode} {$DEFINE RealMode} {$ENDIF}
  6. {$IFDEF ProtMode} sorry, protected mode not supported (yet) {$ENDIF}
  7.  
  8. { nwIPX unit as of 950301 / NwTP 0.6 API. (c) 1993,1995, R.Spronk }
  9.  
  10. INTERFACE
  11.  
  12. Uses Dos,nwMisc;
  13.  
  14. { Primary IPX calls:           Subf:  Comments:
  15.  
  16.   IPXCancelEvent                 6    AES
  17. * IPXCloseSocket                 1    (1)
  18.   IPXDisconnectFromTarget        B    (1)
  19. * IPXGetInterNetworkaddress      9
  20. * IPXGetIntervalMarker           8
  21. * IPXGetLocalTarget              2
  22. - IPXGetPacketSize               D    (IPX internal use only)
  23. * IPXInitialize                       INT 2F
  24. - IPXInitializeNetworkAddress    C    (IPX internal use only)
  25. * IPXListenForPacket             4
  26. * IPXOpenSocket                  0
  27. * IPXRelinquishControl           A
  28. * IPXScheduleIPXEvent            5    AES
  29.   IPXScheduleSpecialEvent        7
  30. * IPXSendPacket                  3
  31. - IPXTerminateSockets            E    (IPX internal use only)
  32.  
  33.   Secondary calls:
  34.  
  35. * IPXpresent
  36. * IPXsetupSendECB
  37. * IPXsetupListenECB
  38.  
  39.   Notes: (1) These functions use INT 21 and are not to be called from
  40.              within an ESR.
  41. }
  42.  
  43. CONST
  44.     LONG_LIVED_SOCKET  = TRUE;   { IPXopenSocket }
  45.     SHORT_LIVED_SOCKET = FALSE;
  46.  
  47.  {*** PACKET TYPES ***}
  48.  
  49.     UNKNOWN_PACKET_TYPE   =0;  { (basic) Unknown IPX packet }
  50.     IPX_PACKET_TYPE       =0;
  51.     RIP_PACKET_TYPE       =1;  { Routing Information Packet }
  52.     ECHO_PACKET_TYPE      =2;
  53.     ERROR_PACKET_TYPE     =3;
  54.     PEP_PACKET_TYPE       =4;  { Packet Exchange Protocol   }
  55.     SPX_PACKET_TYPE       =5;  { Sequenced Packet Protocol Packet }
  56.     PUP_PACKET_TYPE       =12;
  57.     DOD_IP_PACKET_TYPE    =13; { Internet Protocol packet Type }
  58.     NCP_PACKET_TYPE       =17; { NetWare Core Protocol }
  59.     { Experimental packet types: 20 - 37 }
  60.  
  61.  {*** SOCKET NUMBERS ***}
  62.  
  63.     {0001-0BB8 Registered with Xerox                              }
  64.     SKT_XEROX_ROUTING_INFORMATION= $0001;
  65.     SKT_ECHO_PROTOCOL            = $0002;
  66.     SKT_ERROR_HANDLER            = $0003;
  67.  
  68.     {0020-003F Xerox : Experimental                               }
  69.     SKT_NW4_TIME_SYNC_SERVER     = $0040; { used by OT_NW4_TIME_SYNC_SERVER }
  70.     SKT_FILE_SERVICE             = $0451; { see also $8140, used by OT_RSPCX_SERVER }
  71.     SKT_SERVICE_ADVERTISING      = $0452; { SAP }
  72.     SKT_ROUTING_INFORMATION      = $0453; { Novell's RIP Socket   }
  73.     SKT_NETBIOS                  = $0455;
  74.     SKT_DIAGNOSTIC               = $0456;
  75.     { 0457h    ??? (appears to be related to server serial numbers) }
  76.  
  77.     {0BB9-FFFF Xerox : Dynamically assignable Sockets             }
  78.       {0BB9-3FFF Novell:                                              }
  79.       SKT_NMA_AGENT                =$2F90; { used by OT_NMA_AGENT (NMS) }
  80.  
  81.       {4000-7FFF Novell: Dynamically assignable Sockets               }
  82.       { Use a socket in this range for your own applications.         }
  83.       { To avoid conflicts with other programs, you are advised NOT   }
  84.       { to use sockets numbers where the hi-byte equals the low-byte, }
  85.       { C programmers mostly use those to avoid byte-order swapping.  }
  86.  
  87.      { ! See the SKT_XXX file in the XIPX archive for the latest info
  88.        on socket numbers... }
  89.  
  90.       {8000-FFFF Novell: Well known sockets, registered with Novell.  }
  91.       SKT_EMAIL_CHAT               =$8055; { Niche Corp. }
  92.       SKT_EMAIL_CHAT_2             =$8056; { Niche Corp. }
  93.       SKT_BTRIEVE                  =$8058;
  94.       SKT_BTRIEVE_2                =$8059;
  95.       SKT_NW_SQL                   =$805A;
  96.       SKT_NW_SQL_2                 =$805B;
  97.       SKT_GAMESERVER               =$805C;
  98.       SKT_GAMESERVER_2             =$805D;
  99.       SKT_PRINT_SERVER             =$8060;
  100.       SKT_DIGITAL_CHAT             =$806C; { Digital Inc. }
  101.       SKT_NW_ACCESS_SERVER         =$806F;
  102.       SKT_OXXI_EMAIL_CHAT          =$80C3; { Oxxi Inc. }
  103.       SKT_PRINT_SERVER_2           =$811E;
  104.       SKT_INTEL_EMAIL_CHAT         =$845F; { Intel Corp. }
  105.       SKT_WINDOWS_EMAIL_CHAT       =$9017;
  106.       SKT_JOB_SERVER               =$9022;
  107.  
  108. Var Result:word; { unit errorcode variable }
  109.  
  110. Type TipxHeader=Record
  111.                 checksum         :word; { not used, set to $FFFF }
  112.                 length           :word; { total number of bytes }
  113.                 TransportControl :byte; { used by bridges: low 4 bits= hop count }
  114.                 packetType       :byte; { ignored by IPX, used by higher level
  115.                                           protocols only. $00=unknown packet type}
  116.                 destination,
  117.                 source           :TinternetWorkAddress;
  118.                                          { if dest.network equals 0; dest
  119.                                            assumed on same network as sender }
  120.                                          { if dest.node =$FFFFFFFFFFFF, packet
  121.                                            will be sent to all nodes. }
  122.                 end;
  123.     { Fields within IPX and SPX are high-low. Byte swapping will be done
  124.       by the IPX functions, except network and node addresses. }
  125.  
  126.     Tfragment=record { address and size of buffer fragment. }
  127.               Address:Pointer;
  128.               Size:word;
  129.               end;
  130.  
  131.     Tecb=record
  132.          Linkaddress     :Pointer; { used by IPX itself }
  133.          ESRaddress      :Pointer;
  134.          InUseFlag       :Byte; { reset to $00 when request completed }
  135.          CompletionCode  :Byte; { valid after InUseFlag becomes $00;
  136.                                  completionCode=$00: packet sent/received. }
  137.          SocketNumber    :word;
  138.          IPXworkspace    :array[1..4] of byte;
  139.          DriverWorkspace :array[1..12] of byte;
  140.          Immediateaddress:Tnodeaddress; { 6 bytes }
  141.          FragmentCount   :word;  { must be >0 }
  142.          Fragment        :array[1..2] of Tfragment; { [1..FragmentCount] }
  143.                           { The number of fragments is unlimited.
  144.                             However, most applications use 1 or 2. }
  145.          end;
  146.     Tpecb=^Tecb;
  147.  
  148. {    TAESecb=:
  149. Offset    Size    Description
  150.  00h    DWORD    Link
  151.  04h    DWORD    ESR address
  152.  08h    BYTE    in use flag (see below)
  153.  09h  5 BYTEs    AES workspace }
  154.  
  155. Function IpxPresent:boolean;
  156. { Determines if an IPX driver is loaded. Calls IPXInitialize. }
  157.  
  158. Function IPXinitialize:Boolean;
  159. { Determines if an IPX driver is loaded. }
  160.  
  161. {IPX/SPX: 09h}
  162. Function IPXGetInternetworkAddress(Var Address:TinterNetworkAddress):boolean;
  163. { This call returns the network and node address of the requesting workstation. }
  164. { The two byte socketnumber must be appended to the end to form a full }
  165. { 12-Byte network address. The socketnumber will be set to 0000, indicating
  166.   that it has to be filled later with a meaningfule number. }
  167.  
  168. {IPX/SPX: 00h}
  169. Function IPXOpenSocket(Var socket:word; PermanentSocket:boolean):boolean;
  170. { When an application wants to send or receive packets on a socket,
  171.   it should first open the socket. PermanentSocket should be set to TRUE
  172.   if the socket is used by a TSR. This way, the socket will only be
  173.   closed when the IPXcloseSocket function is called. Otherwise, set to FALSE. }
  174.  
  175. {IPX/SPX: 01h}
  176. Function IPXCloseSocket(socket:word):boolean;
  177. { Closes the socket. TSRs should close permanent sockets before terminating. }
  178.  
  179. {IPX/SPX: 02h}
  180. Function IPXGetLocalTarget(Address:TinternetworkAddress;
  181.                            Var ImmAddr:TnodeAddress;
  182.                            Var Ticks:word                ):boolean;
  183. { Returns the nodeaddress (Immediate address) of a bridge/router that
  184.   connects the senders' network with the target-network. If the target
  185.   lies within the same network as the sender, the returned node address
  186.   is the same as the target node-address. }
  187.  
  188. {IPX/SPX: 03h}
  189. Function IPXSendPacket(Var Ecb:Tecb):boolean;
  190. { After calling this function, control is immediately turned back to the
  191.   calling process, whilst in the background the IPX driver is trying to
  192.   send the packet. To check if the message has been sent, check the
  193.   ECB.InUseFlag or use a SendESR.
  194.   The ecb must be filled with appropriate values before calling this function,
  195.   the socket to send on must be open. }
  196.  
  197. {IPX/SPX: 0Fh}
  198. Function IPXInternalSendPacket(Var Ecb:Tecb):boolean;
  199.  
  200. {IPX/SPX: 04h}
  201. Function IPXListenForPacket(Var Ecb:Tecb):Boolean;
  202. { After calling this function, control is immediately turned back to the
  203.   calling process. The IPX driver will wait in the background for a packet
  204.   to be received. To check if a message has been received, check the
  205.   ECB.InUseFlag or use a ListenESR.
  206.   The ecb must be filled with appropriate values before calling this function,
  207.   the socket to receive on must be open. }
  208.  
  209. {IPX/SPX: 0Ah}
  210. Function IPXrelinquishControl:boolean;
  211. { Temporarily gives away CPU time to bakcground processes. This call
  212.   improves efficeincy by informing the IPX driver that the CPU is
  213.   available. }
  214.  
  215. {IPX/SPX: 08h}
  216. Function IPXgetIntervalMarker(Var ticks:word):boolean;
  217. { Gets a time marker from IPX. The difference between two known
  218.   time-markers can be used to determine if a timeout has occurred.
  219.   1 Tick = 1/18.2 second. }
  220.  
  221. {IPX/SPX: 06h}
  222. Function IPXcancelEvent(ECB:Tecb):boolean;
  223. { AES call: Cancel an event.
  224.   When the event is canceled, the ECB.InUseFlag will be set to $00 and the
  225.   ECB.CompletionCode to $FC: Event Canceled. }
  226.  
  227. {IPX/SPX: 0Bh}
  228. Function IPXdisconnectFromTarget(Address:TinternetworkAddress):boolean;
  229. { Informs the listening socket at the specified adress that no more
  230.   packets will be sent to the listening socket.
  231.   This function is not required in your application, it is merely used
  232.   to inform some drivers that the connection (if any) has ended. }
  233.  
  234. {IPX/SPX: 05h}
  235. Function IPXscheduleIPXevent(ticks:word;Var ECB:Tecb):boolean;
  236. { AES call: schedule an event.
  237.   After calling this function, control is immediately turned back to the
  238.   calling process. After waiting the number of ticks specified
  239.   (1 tick= 1/18.2 sec.), the IPX driver activates the ECB.
  240.   This function should never be called with an ECB that is still in use
  241.   by the IPXdriver (i.e. ECB.InUseFlag should be 0 before calling)
  242. }
  243.  
  244. {UPX: 0007}
  245. Function IPXscheduleSpecialEvent(ticks:word;Var ECB:Tecb):boolean;
  246.  
  247. Procedure IpxSpxSystemCall(Var regs:registers);
  248. { Provides an entry into the INT A7 interrupt handler;
  249.   Valid only if IPXinitialize or IPXinstalled were called previously. }
  250.  
  251. {************** Secondary Procedures ***************************************}
  252.  
  253. Procedure IPXSetupListenECB(ESRptr:Pointer; ReceiveSocket:word;
  254.                             BufPtr:Pointer; BufSize:word;
  255.                      {out:} Var IpxHdr:TipxHeader; Var ecb:Tecb);
  256. { Clears IPXheader and ECB, sets values of the required fields within
  257.   the ecb and IPX header. }
  258.  
  259. Procedure IPXsetupSendECB(ESRptr:pointer; SourceSocket:Word;
  260.                           DestAddr:TinterNetworkAddress;
  261.                           BufPtr:pointer; BufSize:word;
  262.                    {out:} Var IpxHdr:TipxHeader; Var ecb:Tecb);
  263. { Clears IPXheader and ECB, sets values of the required fields within
  264.   the ecb and IPX header. }
  265.  
  266. IMPLEMENTATION {==============================================================}
  267.  
  268. CONST
  269.     IPX_MAX_DATA_LENGTH  =546;
  270.  
  271. Var IpxSpxCall:Procedure;
  272.  
  273. Procedure IpxSpxSystemCall(Var regs:registers); assembler;
  274. { This method of calling IPX/SPX is preferred by Novell. }
  275. { For what its' worth: this call is 48 bytes longer than the other one.. }
  276. asm
  277.    { check if IpxSpxCall known. If not, return error $FF in fake AL }
  278. xor ah,ah
  279. mov al,$FF
  280. les di,IpxSpxCall
  281. mov bx,es
  282. cmp bx,$0000
  283. je  @1
  284.    { move fake regs registers to 'real' registers }
  285.    { AX, BX, CX, DX, SI, DI, ES only. }
  286. les di,regs
  287. mov ax,es:[di+16]
  288. push ax            { push new es }
  289. mov ax,es:[di+12]
  290. push ax            { push new di }
  291. mov ax,es:[di]
  292. mov bx,es:[di+2]
  293. mov cx,es:[di+4]
  294. mov dx,es:[di+6]
  295. mov si,es:[di+10]
  296. pop di
  297. pop es
  298.    { farr call to A7 interrup handler }
  299. push bp
  300. CALL IpxSpxCall
  301. pop bp
  302. @1: { move 'real' registers to fake regs registers }
  303. push es
  304. push di
  305. les di,regs
  306. mov es:[di],ax
  307. mov es:[di+2],bx
  308. mov es:[di+4],cx
  309. mov es:[di+6],dx
  310. mov es:[di+10],si
  311. pop ax             { ax:= 'di' }
  312. mov es:[di+12],ax
  313. pop ax             { ax:= 'es' }
  314. mov es:[di+16],ax
  315. end;
  316.  
  317. Function IPXinitialize:Boolean;
  318. CONST DOS_MULTIPLEX =$2F;
  319. Var regs:registers;
  320. begin
  321. Regs.AX:=$7A00;
  322. INTR(DOS_MULTIPLEX,Regs);
  323. if regs.AL<>$FF
  324.  then begin
  325.       Result:=IPX_NOT_INSTALLED;
  326.       IpxInitialize:=false
  327.       end
  328.  else begin
  329.       @IpxSpxCall:=Ptr(Regs.es,Regs.di);
  330.       Result:=0;
  331.       IpxInitialize:=true;
  332.       end;
  333. end;
  334.  
  335. Function IpxPresent:boolean;
  336. begin
  337. IpxPresent:=IpxInitialize
  338. end;
  339.  
  340. {IPX: 09h}
  341. Function IPXGetInternetworkAddress(Var Address:TinterNetworkAddress):boolean;
  342. { This call returns the network and node address of the requesting workstation. }
  343. { The two byte socketnumber must be appended to the end to form a full }
  344. { 12-Byte network address. }
  345. Var regs:registers;
  346. begin
  347. regs.bx:=$0009;
  348. regs.es:=seg(Address);
  349. regs.si:=ofs(Address);
  350. IpxSpxSystemCall(Regs);
  351. result:=regs.al;
  352. address.socket:=$0000; { unknown, to be set later. }
  353. if result<>$FF
  354.  then result:=$00;
  355. IPXGetInternetworkAddress:=(result=$00);
  356. { possible resultcodes: $00 Successful; $FF IPX not initialized }
  357. end;
  358.  
  359. {IPX: 00}
  360. Function IPXOpenSocket(Var socket:word; permanentSocket:boolean):boolean;
  361. Var regs:registers;
  362.     reqForSocket:boolean;
  363. begin
  364. regs.bx:=$0000;
  365. if permanentSocket
  366.  then regs.al:=$FF
  367.  else regs.al:=$00;
  368. regs.dx:=swap(socket); {hi-lo}
  369. reqForSocket:=(socket=$0000);
  370.  
  371. IpxSpxSystemCall(Regs);
  372.  
  373. result:=regs.al;
  374. if reqForSocket
  375.  then socket:=swap(regs.dx); {force lo-hi}
  376. IPXopenSocket:=(result=0);
  377. { resultcodes: $00 successful; $FE Socket Table Is Full;
  378.                $FF socket already open OR IPX not initilazed. }
  379. end;
  380.  
  381. {IPX: 01}
  382. Function IPXCloseSocket(socket:word):boolean;
  383. Var regs:registers;
  384. begin
  385. regs.bx:=$01;
  386. regs.dx:=swap(socket);
  387. IpxSpxSystemCall(regs);
  388. result:=regs.al;
  389. if result<>$FF then result:=$00;
  390. IPXCloseSocket:=(result=$00);
  391. { possible resultcodes: $00 Successful; $FF IPX not initialized }
  392. end;
  393.  
  394.  
  395. {IPX: 02}
  396. Function IPXGetLocalTarget(Address:TinternetworkAddress;
  397.                            Var ImmAddr:TnodeAddress;
  398.                            VAR ticks:Word               ):boolean;
  399. { Ticks = estimated transmission time, in number of ticks (1/18 sec) }
  400. Var reqAddr:TinternetworkAddress;
  401.     repNode:TnodeAddress;
  402.     Regs   :registers;
  403. begin
  404. move(Address,reqAddr,10);
  405. reqAddr.socket:=swap(Address.socket); {hi-lo}
  406. With regs
  407.  do begin
  408.     bx:=$0002;
  409.     es:=seg(reqAddr); si:=ofs(reqAddr); di:=ofs(repNode);
  410.     IpxSpxSystemCall(regs);
  411.     ticks:=regs.cx;
  412.     result:=regs.al;
  413.     if result=0
  414.      then move(repNode,ImmAddr,6);
  415.     end;
  416. IPXGetLocalTarget:=(result=$00);
  417. { resultcodes: $00 Successful; $FA No path to destination node found;
  418.                $FF IPX not initialized. }
  419. end;
  420.  
  421. Function IPXSendPacket(Var Ecb:Tecb):boolean;
  422. { the ecb must be filled, before calling this function }
  423. { Right after this call, IPXrelinquishControl should be called Iteratively,
  424.   this allows the sending of the IPX packet. }
  425. Var regs:Registers;
  426. begin
  427. regs.bx:=$0003;
  428. regs.es:=seg(ecb);
  429. regs.si:=ofs(ecb);
  430. IpxSpxSystemCall(Regs);
  431. result:=regs.al;
  432. if result<>$FF then result:=$00;
  433. IpxSendPacket:=(result=$00);
  434. { possible resultcodes: $00 Successful; $FF IPX not initialized }
  435. end;
  436.  
  437.  
  438. Function IPXInternalSendPacket(Var Ecb:Tecb):boolean;
  439. Var regs:Registers;
  440. begin
  441. regs.bx:=$000F;
  442. regs.es:=seg(ecb);
  443. regs.si:=ofs(ecb);
  444. IpxSpxSystemCall(Regs);
  445. result:=regs.al;
  446. if result<>$FF then result:=$00;
  447. IpxInternalSendPacket:=(result=$00);
  448. { possible resultcodes: $00 Successful; $FF IPX not initialized }
  449. end;
  450.  
  451.  
  452. Function IPXListenForPacket(Var Ecb:Tecb):Boolean;
  453. { socket must be opened, ECB (partly) filled. }
  454. Var regs:Registers;
  455. begin
  456. regs.bx:=$0004;
  457. regs.es:=seg(ecb);
  458. regs.si:=ofs(ecb);
  459. IpxSpxSystemCall(Regs);
  460. result:=regs.al;
  461. if result<>$FF
  462.  then result:=$00;
  463. IpxListenForPacket:=(result=$00);
  464. {resultcodes: $00 Successful;
  465.               $FF Listening Socket doesn't exist OR IPX not initialized }
  466. end;
  467.  
  468. Function IPXrelinquishControl:boolean;
  469. Var regs:Registers;
  470. begin
  471. regs.bx:=$000A;
  472. IpxSpxSystemCall(Regs);
  473. result:=regs.al;
  474. if result<>$FF then result:=$00;
  475. IpxrelinquishControl:=(result=$00);
  476. {resultcodes: $00 Successful; $FF IPX not initialized }
  477. end;
  478.  
  479. Function IPXgetIntervalMarker(Var ticks:word):boolean;
  480. Var regs:Registers;
  481. begin
  482. regs.bx:=$0008;
  483. IpxSpxSystemCall(Regs);
  484. ticks:=regs.ax;
  485. result:=$00;
  486. IPXgetIntervalMarker:=True;
  487. end;
  488.  
  489. Function IPXcancelEvent(ECB:Tecb):boolean;
  490. Var regs:registers;
  491. begin
  492. regs.bx:=$0006;
  493. regs.es:=seg(ecb);
  494. regs.si:=ofs(ecb);
  495. IpxSpxSystemCall(Regs);
  496. result:=regs.al;
  497. IPXcancelEvent:=(result=0);
  498. { resultcodes: 00 Successful; F9 ECB cannot be canceled;
  499.                FF ECB not in use OR IPX not initialized. }
  500. end;
  501.  
  502. Function IPXdisconnectFromTarget(Address:TinternetworkAddress):boolean;
  503. VAR regs:registers;
  504.     LocAddr:TinternetworkAddress;
  505. begin
  506. move(Address,LocAddr,10);
  507. LocAddr.socket:=swap(Address.socket);
  508. regs.bx:=$000B;
  509. regs.es:=seg(LocAddr);
  510. regs.si:=ofs(LocAddr);
  511. IpxSpxSystemCall(Regs);
  512. result:=regs.al;
  513. if result<>$FF
  514.  then result:=$00;
  515. IPXdisconnectFromTarget:=(result=0);
  516. {resultcodes: $00 Successful; $FF IPX not initialized }
  517. end;
  518.  
  519. Function IPXscheduleIPXevent(ticks:word;Var ECB:Tecb):boolean;
  520. Var regs:registers;
  521. begin
  522. regs.bx:=$0005;
  523. regs.ax:=ticks;
  524. regs.es:=seg(ECB);
  525. regs.si:=ofs(ECB);
  526. IpxSpxSystemCall(Regs);
  527. if result<>$FF
  528.  then result:=$00;
  529. IPXscheduleIPXevent:=(result=0);
  530. {resulcodes: 00 successful; FF IPX not initialized }
  531. end;
  532.  
  533. Function IPXscheduleSpecialEvent(ticks:word;Var ECB:Tecb):boolean;
  534. Var regs:registers;
  535. begin
  536. regs.bx:=$0007;
  537. regs.ax:=ticks;
  538. regs.es:=seg(ECB);
  539. regs.si:=ofs(ECB);
  540. IpxSpxSystemCall(Regs);
  541. if result<>$FF
  542.  then result:=$00;
  543. IPXscheduleSpecialEvent:=(result=0);
  544. {resulcodes: 00 successful; FF IPX not initialized }
  545. end;
  546.  
  547. {************** Secondary Procedures ***************************************}
  548.  
  549. Procedure IPXSetupListenECB(ESRptr:Pointer;ReceiveSocket:word;
  550.                             BufPtr:Pointer;BufSize:word;
  551.                      {out:} Var IpxHdr:TipxHeader; Var ecb:Tecb);
  552. { Clears IPXheader and ECB, sets values of the required fields within
  553.   the ecb and IPX header. }
  554. { ECB: ESR adress field, socket number, fragment count, frag.descriptor fields }
  555. begin
  556. FillChar(ecb,SizeOf(Tecb),#0);
  557. FillChar(ipxHdr,SizeOF(TipxHeader),#0);
  558. WITH ECB
  559.  do begin
  560.     if ESRptr<>NIL
  561.      then ESRaddress:=ESRptr;
  562.     Fragmentcount:=2;
  563.     socketNumber:=swap(ReceiveSocket); {hi-lo}
  564.  
  565.     Fragment[1].Address:=@ipxHdr;
  566.     Fragment[2].Address:=BufPtr;
  567.     Fragment[1].size:=SizeOf(Tipxheader);
  568.     Fragment[2].size:=BufSize;
  569.     end;
  570. end;
  571.  
  572. Procedure IPXsetupSendECB(ESRptr:pointer; SourceSocket:word;
  573.                           DestAddr:TinterNetworkAddress;
  574.                           BufPtr:pointer; BufSize:word;
  575.                    {out:} Var IpxHdr:TipxHeader; Var ecb:Tecb);
  576. { Clears IPXheader and ECB, sets values of the required fields within
  577.   the ecb and IPX header. }
  578. Var ImmAddr:TnodeAddress;
  579.     Ticks:word;
  580. begin
  581. fillchar(ipxHdr,SizeOf(TipxHeader),#0);
  582. with ipxhdr
  583.  do begin
  584.     PacketType:=IPX_PACKET_TYPE;
  585.     Move(DestAddr,Destination,10);
  586.     destination.socket:=swap(DestAddr.socket); {hi-lo}
  587.     end;
  588. IPXGetLocalTarget(DestAddr,ImmAddr,Ticks);
  589. fillchar(ecb,sizeOf(ecb),#0);
  590. With ecb
  591.  do begin
  592.     if ESRptr<>NIL
  593.      then ESRaddress:=ESRptr;
  594.     socketNumber:=swap(SourceSocket); {hi-lo}
  595.     Move(ImmAddr,ImmediateAddress,6);
  596.     FragmentCount:=2;
  597.     fragment[1].Address:=@ipxhdr;
  598.     fragment[1].size:=SizeOf(TipxHeader);
  599.     fragment[2].Address:=BufPtr;
  600.     fragment[2].size:=BufSize;
  601.     end;
  602. end;
  603.  
  604.  
  605.  
  606. end.
  607.